home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Screenblankers / Rotor / Rotor.c < prev    next >
C/C++ Source or Header  |  1996-09-26  |  47KB  |  1,799 lines

  1. /*
  2.  
  3.    Rotor V1.01
  4.  
  5.    Written by Markus "ill" Illenseer    markus@Techfak.Uni-Bielefeld.de
  6.  
  7.    Based on ASwarm II V1.4 by Matthias Scheler and Markus Illenseer.
  8.  
  9.    Please leave this source intact. Rotor is freely distributable.
  10.    If you have suggestions or Bug-Reports, please contact me.
  11.  
  12.    Read the Manuals for known Bugs and Contact-Adresses.
  13.  
  14. */
  15.  
  16. #include <hardware/custom.h>
  17. #include <hardware/dmabits.h>
  18. #include <exec/memory.h>
  19. #include <exec/ports.h>
  20. #include <exec/execbase.h>
  21. #include <graphics/displayinfo.h>
  22. #include <graphics/gfxbase.h>
  23. #include <graphics/gfxmacros.h>
  24. #include <intuition/intuitionbase.h>
  25. #include <intuition/gadgetclass.h>
  26. #include <libraries/commodities.h>
  27. #include <libraries/gadtools.h>
  28. #include <workbench/startup.h>
  29. #include <workbench/icon.h>
  30. #include <workbench/workbench.h>
  31. #include <dos/dosextens.h>
  32. #include <dos/dostags.h>
  33. #include <dos/rdargs.h>
  34.  
  35. #include <clib/commodities_protos.h>
  36. #include <clib/dos_protos.h>
  37. #include <clib/exec_protos.h>
  38. #include <clib/gadtools_protos.h>
  39. #include <clib/graphics_protos.h>
  40. #include <clib/icon_protos.h>
  41. #include <clib/intuition_protos.h>
  42. #include <clib/macros.h>
  43.  
  44. #include <string.h>
  45. #include <stdlib.h>
  46. #include <math.h>
  47.  
  48. #ifdef LATTICE /* some stuff for SAS-C */
  49.  
  50. #include <pragmas/commodities_pragmas.h>
  51. #include <pragmas/dos_pragmas.h>
  52. #include <pragmas/exec_pragmas.h>
  53. #include <pragmas/gadtools_pragmas.h>
  54. #include <pragmas/graphics_pragmas.h>
  55. #include <pragmas/icon_pragmas.h>
  56. #include <pragmas/intuition_pragmas.h>
  57.  
  58. #define VOID_INTERRUPT void __interrupt __saveds
  59. #define REGARGS        __regargs
  60. #define VOID_STDARGS   void __stdargs
  61.  
  62. CxObj *HotKey(UBYTE *,struct MsgPort *,long);
  63. void NewList(struct List *);
  64.  
  65. UBYTE *VersionString = "$VER: Rotor V1.01 (compiled with SAS/C)";
  66.  
  67. void chkabort(void)
  68. {}
  69.  
  70. #else /* some stuff for Dice especially for -mR */
  71.  
  72. #define VOID_INTERRUPT __stkargs __geta4 void
  73. #define REGARGS
  74. #define VOID_STDARGS   __stkargs void
  75.  
  76. __stkargs CxObj *HotKey(UBYTE *,struct MsgPort *,long);
  77. __stkargs void NewList(struct List *);
  78.  
  79. UBYTE *VersionString = "$VER: Rotor V1.01 (compiled with DICE)";
  80.  
  81. void main(LONG,UBYTE **);
  82.  
  83. void wbmain(struct WBStartup *WBS)
  84.  
  85. {
  86.  if (WBS->sm_NumArgs) (void)CurrentDir(WBS->sm_ArgList->wa_Lock);
  87.  
  88.  main(0L,(UBYTE **)WBS);
  89. }
  90.  
  91. #endif
  92.  
  93. /*
  94.  
  95.    Common Definitions
  96.  
  97. */
  98.  
  99. #define custom (*((struct Custom *)0xDFF000L))
  100.  
  101. extern struct ExecBase *SysBase;
  102. extern struct DosLibrary *DOSBase;
  103.  
  104. #define FINDPROCPORT (&((struct Process *)SysBase->ThisTask)->pr_MsgPort)
  105.  
  106. struct IntuitionBase *IntuitionBase;
  107. struct GfxBase *GfxBase;
  108.  
  109. struct Library *CxBase,*GadToolsBase,*IconBase;
  110.  
  111. LONG WBStarted;
  112.  
  113. #define NUMTOOLTYPES 11
  114.  
  115. char *ToolTypeIDs[NUMTOOLTYPES] =
  116.  {"CX_PRIORITY","CX_POPUP","CX_POPKEY","BLANKKEY",
  117.   "TIMEOUT","CLIENTTIMEOUT","CYCLE",
  118.   "DISPLAY","MOUSEBLANKMETHOD","CHANGE","TRAIL"};
  119.  
  120. /*
  121.  
  122.    Definitions for our Commodity
  123.  
  124. */
  125.  
  126. struct NewBroker NewBroker =
  127.  {NB_VERSION,"Rotor","Amiga Rotor 1.01","Screen Blanker by Markus Illenseer",
  128.   NBU_NOTIFY|NBU_UNIQUE,COF_SHOW_HIDE,0,NULL,0};
  129. CxObj *Broker,*PopKeyFilter,*BlankKeyFilter;
  130. struct MsgPort *CxPort;
  131. LONG CxPri,CxPopUp;
  132.  
  133. UBYTE PopKey[32],BlankKey[32];
  134.  
  135. #define EVENT_OPEN_WINDOW 1L
  136. #define EVENT_BLANK       2L
  137.  
  138. #define DEF_CX_PRI 0L
  139. #define DEF_POPKEY   "CONTROL ALT r"     /* Hot Key for the Edit Window */
  140. #define DEF_BLANKKEY "CONTROL ALT b"     /* Hot Key for immediate Blank */
  141.  
  142. LONG TimeLeft,InitTimeLeft,TimeOut,ClientTimeOut;
  143.  
  144. #define MAX_TIMEOUT        3600L
  145. #define MAX_CLIENT_TIMEOUT 60L
  146.  
  147. #define DEF_TIMEOUT        60L
  148. #define DEF_CLIENT_TIMEOUT 5L
  149.  
  150. #define SERVER_PRI 5L                 /* Don't change this, saves live */
  151. #define CLIENT_PRI -40L
  152.  
  153. /*
  154.  
  155.    Definitions for our Blanker Screen
  156.  
  157. */
  158.  
  159. struct ModeNode
  160.  {
  161.   struct Node mn_Node;
  162.   UWORD mn_Index;
  163.   ULONG mn_DisplayID;
  164.   char mn_Name[DISPLAYNAMELEN];
  165.  };
  166.  
  167. struct List *ModeList;
  168. struct ModeNode *DisplayMode;
  169.  
  170. #define FindMode(l,n) ((struct ModeNode *)FindName(l,n))
  171.  
  172. #define DEF_MODE      HIRES
  173. #define DEF_MODE_NAME "HighRes"
  174.  
  175. /* Mini and Maximum definitions for possible parameters */
  176.  
  177. #define MAX_CHANGE 10000
  178. #define DEF_CHANGE 1000
  179.  
  180. #define MAX_TRAIL 2000
  181. #define DEF_TRAIL 200
  182.  
  183. char *Template = /* extra extra extra long :-) */
  184.  "CX_PRIORITY/N/K,CX_POPKEY/K,CX_POPUP/S,BLANKKEY/K,SECONDS=TIMEOUT/N/K,"
  185.  "CLIENTTIMEOUT/N/K,DISPLAY/K,CYCLE/S,MOUSEBLANKMETHOD/K,CHANGE/N/K,TRAIL/N/K";
  186.  
  187. /*
  188.  
  189.    Definitions for our Configuration Window
  190.  
  191. */
  192.  
  193. #ifndef WFLG_NEWLOOKMENUS
  194. #define WFLG_NEWLOOKMENUS   0x200000L
  195. #endif
  196.  
  197. WORD LeftEdge=68,TopEdge=13;     /* Hard Coded, the window is too big to */
  198. struct Window *BlankerWindow;    /* let it open under the mouse pointer */
  199.  
  200. #define GID_HIDE      0  /* The Gadget-ID's */
  201. #define GID_BLANK     1
  202. #define GID_QUIT      2
  203. #define GID_MODE      3
  204. #define GID_TIMEOUT   4
  205. #define GID_CLIENT    5
  206. #define GID_MOUSE     6
  207. #define GID_POPKEY    7
  208. #define GID_BLANKKEY  8
  209. #define GID_CHANGE    9
  210. #define GID_TRAIL    10
  211. #define GID_CYCLE    11
  212.  
  213. #define NUM_GADS 12
  214.  
  215. char *MouseBlankMethods[] = /* List of Mouse Blank Methods */
  216.  {"Hardware","FreeSprite",NULL};
  217.  
  218. struct VisualInfo *BlankerVisualInfo;
  219. struct Menu *BlankerMenu;
  220. struct Gadget *BlankerContext,*BlankerGadgets[NUM_GADS];
  221. struct TextAttr BlankerAttr={"topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT};
  222.  
  223. #ifndef GTMN_NewLookMenus
  224. #define GTMN_NewLookMenus (TAG_USER+0x80043)
  225. #endif
  226.  
  227. struct NewMenu NewBlankerMenus[] =
  228.  {NM_TITLE,"Project",NULL,0,0L,NULL,
  229.   NM_ITEM,"Load Config","L",0,0L,NULL,
  230.   NM_ITEM,"Save Config","S",0,0L,NULL,
  231.   NM_ITEM,NM_BARLABEL,NULL,0,0L,NULL,
  232.   NM_ITEM,"About ...",NULL,0,0L,NULL,
  233.   NM_ITEM,NM_BARLABEL,NULL,0,0L,NULL,
  234.   NM_ITEM,"Hide","H",0,0L,NULL,
  235.   NM_ITEM,"Quit","Q",0,0L,NULL,
  236.   NM_TITLE,"Edit",NULL,0,0L,NULL,
  237.   NM_ITEM,"Reset To Defaults","D",0,0L,NULL,
  238.   NM_END,NULL,NULL,0,0L,NULL};
  239.  
  240. struct NewGadget NewBlankerGadgets[NUM_GADS] =
  241.  {16,101,48,12,"_Hide",&BlankerAttr,GID_HIDE,PLACETEXT_IN,NULL,NULL,
  242.  
  243.   98,101,48,12,"_Blank",&BlankerAttr,GID_BLANK,PLACETEXT_IN,NULL,NULL,
  244.  
  245.   180,101,48,12,"_Quit",&BlankerAttr,GID_QUIT,PLACETEXT_IN,NULL,NULL,
  246.  
  247.   240,55,272,58,"Display Mode",&BlankerAttr,
  248.   GID_MODE,PLACETEXT_ABOVE,NULL,NULL,
  249.  
  250.   172,10,56,12,"_Timeout",&BlankerAttr,GID_TIMEOUT,PLACETEXT_LEFT,NULL,NULL,
  251.  
  252.   172,24,56,12,"C_lient Timeout",&BlankerAttr,
  253.   GID_CLIENT,PLACETEXT_LEFT,NULL,NULL,
  254.  
  255.   104,55,124,12,"_Mouse Blank",&BlankerAttr,GID_MOUSE,PLACETEXT_LEFT,NULL,NULL,
  256.  
  257.   324,10,188,12,"_Pop Key",&BlankerAttr,GID_POPKEY,PLACETEXT_LEFT,NULL,NULL,
  258.  
  259.   324,24,188,12,"Blank _Key",&BlankerAttr,
  260.   GID_BLANKKEY,PLACETEXT_LEFT,NULL,NULL,
  261.  
  262.   128,69,100,12,"_Change        ",&BlankerAttr,
  263.   GID_CHANGE,PLACETEXT_LEFT,NULL,NULL,
  264.  
  265.   128,83,100,12,"_Trail         ",&BlankerAttr,
  266.   GID_TRAIL,PLACETEXT_LEFT,NULL,NULL ,
  267.  
  268.   202,43,16,12,"C_olor Cycling",&BlankerAttr,
  269.   GID_CYCLE,PLACETEXT_LEFT,NULL,NULL };
  270.  
  271. UBYTE BlankerGadgetKinds[NUM_GADS] =
  272.  {BUTTON_KIND,BUTTON_KIND,BUTTON_KIND,LISTVIEW_KIND,
  273.   INTEGER_KIND,INTEGER_KIND,CYCLE_KIND,
  274.   STRING_KIND,STRING_KIND,SLIDER_KIND,SLIDER_KIND,CHECKBOX_KIND};
  275.  
  276. struct TagItem BlankerGadgetTags[] =
  277.  {GTLV_Labels,0L,GTLV_Selected,0L,GTLV_ShowSelected,NULL,TAG_DONE,0L,
  278.   GTIN_Number,0L,GTIN_MaxChars,4L,TAG_DONE,0L,
  279.   GTIN_Number,0L,GTIN_MaxChars,2L,TAG_DONE,0L,
  280.   GTCY_Labels,NULL,GTCY_Active,0,TAG_DONE,0L,
  281.  
  282.   GTST_String,0L,GTST_MaxChars,31L,TAG_DONE,0L,
  283.   GTST_String,0L,GTST_MaxChars,31L,TAG_DONE,0L,
  284.  
  285.   GTSL_Min,1L,GTSL_Max,MAX_CHANGE,GTSL_Level,0L,
  286.   GTSL_MaxLevelLen,5L,GTSL_LevelFormat,(ULONG)"%5ld",
  287.   GA_RelVerify,TRUE,PGA_Freedom,LORIENT_HORIZ,TAG_DONE,0L,
  288.  
  289.   GTSL_Min,2L,GTSL_Max,MAX_TRAIL,GTSL_Level,0L,
  290.   GTSL_MaxLevelLen,5L,GTSL_LevelFormat,(ULONG)"%4ld",
  291.   GA_RelVerify,TRUE,PGA_Freedom,LORIENT_HORIZ,TAG_DONE,0L ,
  292.  
  293.   GTCB_Checked,0L,TAG_DONE,0L };
  294.  
  295. UBYTE BlankerTagsIndex[NUM_GADS] = {3,3,3,0,4,7,10,13,16,19,27,35};
  296.  
  297. struct EasyStruct AboutEasyStruct =
  298.  {sizeof(struct EasyStruct),0L,"About ...",
  299.   "Rotor V1.01\n"
  300.   "© 1993 by Markus Illenseer\n"
  301.   "Have fun.","Ok"};
  302.  
  303. /*
  304.  
  305.     Definitions for Server/Client Communication
  306.  
  307. */
  308.  
  309. BYTE bsp_TimeOut,bsp_InputSig,bsp_ClientSig;
  310. struct Task *BlankerServerProcess;
  311.  
  312. #define MASK(n) (1L<<(n))
  313.  
  314. struct BlankerClientMsg
  315.  {
  316.   struct Message bcm_Message;
  317.   struct Screen *bcm_Screen;
  318.   LONG bcm_Status;
  319.   ULONG bcm_SigMask;
  320.   LONG bmc_MouseBlank,bcm_Change,bcm_Trail;
  321.   LONG bcm_Cycle;
  322.  } BlankerClientMsg;
  323.  
  324. /*
  325.  
  326.    Definitions for Rotor Stuff
  327.  
  328. */
  329.  
  330. /*#define SAVE     200*/  /* this is a good constant to tweak */
  331. #define REPS      50
  332. #define BORDER    1
  333. #define SIZEFACTOR 3000.0
  334.  
  335. #define MAXANGLE  10000  /* irrectangular */
  336. #define DEFAULTCOUNT  3
  337.  
  338. typedef unsigned char Boolean;
  339.  
  340. struct elem {
  341.     float       angle;
  342.     float       radius;
  343.     float       start_radius;
  344.     float       end_radius;
  345.     float       radius_drift_max;
  346.     float       radius_drift_now;
  347.  
  348.     float       ratio;
  349.     float       start_ratio;
  350.     float       end_ratio;
  351.     float       ratio_drift_max;
  352.     float       ratio_drift_now;
  353. };
  354.  
  355. typedef struct flightstruct {
  356.     struct elem *elements;
  357.     int         pix;
  358.     int         lastx,
  359.                 lasty;
  360.     int         num,
  361.                 rotor,
  362.                 prev;
  363.     int         *savex,
  364.                 *savey;
  365.     float       angle;
  366.     int         centerx,
  367.                 centery;
  368.     int         height, width;
  369.     int         Trail;
  370.     Boolean     firsttime;
  371.     Boolean     forward;
  372.     Boolean     unused;
  373.     Boolean     smallscreen;    /* for small viewmodes */
  374. }           flightstruct;
  375.  
  376.  
  377. #define ROTOR_COL_NUM 33
  378.  
  379. UWORD RotorColors[ROTOR_COL_NUM] =  /* Color Cycling Table */
  380.  {0x000F,0x000F,0x004F,0x008F,0x00BF,0x00FF,0x00FB,0x00F7,0x00F3,0x00F0,0x04F0,
  381.   0x08F0,0x09F0,0x0AF0,0x0BF0,0x0CF0,0x0DF0,0x0EF0,0x0FF0,0x0FE0,0x0FD0,0x0FC0,
  382.   0x0FB0,0x0F90,0x0F80,0x0F70,0x0F60,0x0F50,0x0F40,0x0F30,0x0F20,0x0F10,0x0F00};
  383.  
  384.  
  385. UWORD Colors[4] = {0x0000,0x0FFF};
  386.  
  387. #define RAND(m) (Random(m)-(m)/2)
  388.  
  389. LONG MouseBlank,Change,Trail,Cycle;
  390.  
  391. /*
  392.  
  393.     The following functions are taken from Mattias's resource tracker library for
  394.     SAS/C. I normally use to link the programs with this library, but to make
  395.     it possible for other people to compile Rotor included the required
  396.     source codes. Thanks Matthias!
  397.  
  398. */
  399.  
  400. struct ToolNode
  401.  {
  402.   struct ToolNode *Next;
  403.   void *Tool;
  404.   void (*RemProc)(void *,LONG); /* requires stack arguments !!! */
  405.   LONG Size;
  406.  } *ToolList;
  407.  
  408. void REGARGS RemTool(void *Tool)
  409.  
  410. {
  411.  struct ToolNode **Ptr,*ToolNode;
  412.  
  413.  Ptr=&ToolList;
  414.  while (ToolNode=*Ptr)
  415.   if (ToolNode->Tool==Tool)
  416.    {
  417.     *Ptr=ToolNode->Next;
  418.  
  419.     ToolNode->RemProc(ToolNode->Tool,ToolNode->Size);
  420.     FreeVec ((APTR)ToolNode);
  421.  
  422.     return;
  423.    }
  424.   else Ptr=&ToolNode->Next;
  425. }
  426.  
  427. VOID_STDARGS RemoveAll(void)
  428.  
  429. {
  430.  while (ToolList) RemTool (ToolList->Tool);
  431. }
  432.  
  433. void REGARGS AddTool(void *NewTool,void *ProcPtr,LONG NewSize)
  434.  
  435. {
  436.  struct ToolNode *Ptr;
  437.  void (*NewRemProc)(void *,LONG);
  438.  static BOOL First=TRUE;
  439.  
  440.  NewRemProc=(void (*)(void *,LONG))ProcPtr;
  441.  if (NewTool==NULL) exit (10);
  442.  
  443.  if (First)
  444.   {
  445.    First=FALSE;
  446.    if (atexit(RemoveAll))
  447.     {
  448.      NewRemProc (NewTool,NewSize);
  449.      exit (20);
  450.     }
  451.   }
  452.  
  453.  if ((Ptr=AllocVec(sizeof(struct ToolNode),0L))==NULL)
  454.   {
  455.    NewRemProc (NewTool,NewSize);
  456.    exit (20);
  457.   }
  458.  Ptr->Next=ToolList;
  459.  Ptr->Tool=NewTool;
  460.  Ptr->RemProc=NewRemProc;
  461.  Ptr->Size=NewSize;
  462.  ToolList=Ptr;
  463. }
  464.  
  465. /*
  466.  
  467.    Some useful functions
  468.  
  469. */
  470.  
  471. VOID_STDARGS DeleteMsgPortSafely(struct MsgPort *AnyPort)
  472.  
  473. {
  474.  struct Message *AnyMsg;
  475.  
  476.  while (AnyMsg=GetMsg(AnyPort)) ReplyMsg (AnyMsg);
  477.  DeleteMsgPort (AnyPort);
  478. }
  479.  
  480. LONG RDArgsLong(LONG Param,LONG Default,LONG Min,LONG Max)
  481.  
  482. {
  483.  LONG *Ptr;
  484.  
  485.  if ((Ptr=(LONG *)Param)==NULL) return Default;
  486.  
  487.  if ((*Ptr<Min)||(*Ptr>Max)) return Default;
  488.  else return *Ptr;
  489. }
  490.  
  491. UWORD PutChar[2] = {0x16C0,0x4E75};
  492.  
  493. /* dirty hack to avoid assembler part :-)
  494.  
  495.    16C0: move.b d0,(a3)+
  496.    4E75: rts
  497. */
  498.  
  499. VOID_STDARGS SPrintF(char *Buffer,char *FormatString,...)
  500.  
  501. {
  502.  RawDoFmt (FormatString,(APTR)((LONG *)&FormatString+1L),
  503.            (void *)PutChar,Buffer);
  504. }
  505.  
  506. /*
  507.  
  508.    Functions for Handling the List of the avaible Graphics Modes
  509.  
  510. */
  511.  
  512. VOID_STDARGS DeleteModeList(struct List *ModeList)
  513.  
  514. {
  515.  struct ModeNode *ModeNode;
  516.  
  517.  while (ModeList->lh_Head->ln_Succ)
  518.   {
  519.    ModeNode=(struct ModeNode *)ModeList->lh_Head;
  520.    RemHead (ModeList);
  521.    FreeVec ((APTR)ModeNode);
  522.   }
  523.  FreeVec ((APTR)ModeList);
  524. }
  525.  
  526. struct List *CreateModeList(void)
  527.  
  528. {
  529.  struct List *ModeList;
  530.  UWORD Num;
  531.  ULONG DisplayID;
  532.  struct DimensionInfo DimInfo;
  533.  struct NameInfo NameInfo;
  534.  struct ModeNode *ModeNode;
  535.  
  536.  if (ModeList=AllocVec(sizeof(struct List),MEMF_PUBLIC)) NewList (ModeList);
  537.  else return NULL;
  538.  
  539.  Num=0;
  540.  DisplayID=INVALID_ID;
  541.  while ((DisplayID=NextDisplayInfo(DisplayID))!=INVALID_ID)
  542.   if ((DisplayID&MONITOR_ID_MASK)&&(ModeNotAvailable(DisplayID)==0L))
  543.    if (GetDisplayInfoData(NULL,(UBYTE *)&DimInfo,sizeof(struct DimensionInfo),
  544.                           DTAG_DIMS,DisplayID))
  545.     if (DimInfo.MaxDepth>1)
  546.      if (GetDisplayInfoData(NULL,(UBYTE *)&NameInfo,sizeof(struct NameInfo),
  547.                             DTAG_NAME,DisplayID))
  548.       if (ModeNode=AllocVec(sizeof(struct ModeNode),MEMF_PUBLIC))
  549.        {
  550.         (void)strcpy(ModeNode->mn_Node.ln_Name=ModeNode->mn_Name,
  551.                      NameInfo.Name);
  552.         ModeNode->mn_Index=Num++;
  553.         ModeNode->mn_DisplayID=DisplayID;
  554.         AddTail (ModeList,&ModeNode->mn_Node);
  555.        }
  556.  
  557.  if (ModeList->lh_Head->ln_Succ==NULL)
  558.   if (ModeNode=AllocVec(sizeof(struct ModeNode),MEMF_PUBLIC))
  559.    {
  560.     (void)strcpy(ModeNode->mn_Node.ln_Name=ModeNode->mn_Name,DEF_MODE_NAME);
  561.     ModeNode->mn_Index=Num;
  562.     ModeNode->mn_DisplayID=DEF_MODE;
  563.     AddTail (ModeList,&ModeNode->mn_Node);
  564.    }
  565.   else
  566.    {
  567.     FreeVec ((APTR)ModeList);
  568.     return NULL;
  569.    }
  570.  
  571.  return ModeList;
  572. }
  573.  
  574. struct ModeNode *GetDefaultMode(struct List *ModeList)
  575.  
  576. {
  577.  struct NameInfo NameInfo;
  578.  struct ModeNode *ModeNode;
  579.  
  580.  if (GetDisplayInfoData(NULL,(UBYTE *)&NameInfo,sizeof(struct NameInfo),
  581.                         DTAG_NAME,DEF_MODE))
  582.   if (ModeNode=FindMode(ModeList,NameInfo.Name)) return ModeNode;
  583.  
  584.  return (struct ModeNode *)ModeList->lh_Head;
  585. }
  586.  
  587. struct ModeNode *GetIndexMode(struct List *ModeList,UWORD Index)
  588.  
  589. {
  590.  struct ModeNode *ModeNode;
  591.  
  592.  ModeNode=(struct ModeNode *)ModeList->lh_Head;
  593.  while (ModeNode->mn_Node.ln_Succ)
  594.   if (ModeNode->mn_Index==Index) return ModeNode;
  595.   else ModeNode=(struct ModeNode *)ModeNode->mn_Node.ln_Succ;
  596.  
  597.  return (struct ModeNode *)ModeList->lh_Head;
  598. }
  599.  
  600. /*
  601.  
  602.    "icon.library" Stuff
  603.  
  604. */
  605.  
  606. char REGARGS *YesNo(LONG Flag)
  607.  
  608. {
  609.  return Flag?"YES":"NO";
  610. }
  611.  
  612. char REGARGS *ToolTypeString(struct DiskObject *DiskObject,char *ID,
  613.                              char *Default)
  614.  
  615. {
  616.  char *String;
  617.  
  618.  if (DiskObject==NULL) return Default;
  619.  
  620.  if (String=FindToolType(DiskObject->do_ToolTypes,ID)) return String;
  621.  else return Default;
  622. }
  623.  
  624. LONG REGARGS ToolTypeBoolean(struct DiskObject *DiskObject,char *ID,
  625.                              LONG Default)
  626.  
  627. {
  628.  if (Default) return (stricmp(ToolTypeString(DiskObject,ID,""),
  629.                               YesNo(FALSE))!=0);
  630.  else return (stricmp(ToolTypeString(DiskObject,ID,""),YesNo(TRUE))==0);
  631. }
  632.  
  633. LONG REGARGS ToolTypeLong(struct DiskObject *DiskObject,char *ID,LONG Default,
  634.                           LONG Min,LONG Max)
  635.  
  636. {
  637.  char *String;
  638.  
  639.  if (DiskObject==NULL) return Default;
  640.  
  641.  if (String=FindToolType(DiskObject->do_ToolTypes,ID))
  642.   {
  643.    LONG Value;
  644.  
  645.    Value=atol(String);
  646.    if ((Value<Min)||(Value>Max)) return Default;
  647.    else return Value;
  648.   }
  649.  else return Default;
  650. }
  651.  
  652. void REGARGS LoadConfig(char *Name)
  653.  
  654. {
  655.  struct DiskObject *DiskObject;
  656.  
  657.  if (Name) DiskObject=GetDiskObject(Name);
  658.  else DiskObject=NULL;
  659.  
  660.  CxPri=ToolTypeLong(DiskObject,ToolTypeIDs[0],0L,-128L,127L);
  661.  CxPopUp=ToolTypeBoolean(DiskObject,ToolTypeIDs[1],TRUE);
  662.  (void)strcpy(PopKey,ToolTypeString(DiskObject,ToolTypeIDs[2],DEF_POPKEY));
  663.  (void)strcpy(BlankKey,ToolTypeString(DiskObject,ToolTypeIDs[3],DEF_BLANKKEY));
  664.  
  665.  /* get Time Out, Client Time Out and Display mode */
  666.  
  667.  if ((TimeOut=ToolTypeLong(DiskObject,"SECONDS",0L,1L,MAX_TIMEOUT))==0L)
  668.   TimeOut=ToolTypeLong(DiskObject,ToolTypeIDs[4],DEF_TIMEOUT,1L,MAX_TIMEOUT);
  669.  
  670.  ClientTimeOut=ToolTypeLong(DiskObject,ToolTypeIDs[5],
  671.                             DEF_CLIENT_TIMEOUT,1L,MAX_CLIENT_TIMEOUT);
  672.  if ((DisplayMode=FindMode(ModeList,ToolTypeString(DiskObject,ToolTypeIDs[6],
  673.                                                    "")))==NULL)
  674.   DisplayMode=GetDefaultMode(ModeList);
  675.  
  676.  if (stricmp(ToolTypeString(DiskObject,ToolTypeIDs[7],""),
  677.              MouseBlankMethods[1])) MouseBlank=0L;
  678.  else MouseBlank=1L;
  679.  
  680.  Change=ToolTypeLong(DiskObject,ToolTypeIDs[8],DEF_CHANGE,1L,MAX_CHANGE);
  681.  Trail=ToolTypeLong(DiskObject,ToolTypeIDs[9],DEF_TRAIL,2L,MAX_TRAIL);
  682.  Cycle=ToolTypeBoolean(DiskObject,ToolTypeIDs[10],TRUE);
  683.  
  684.  if (BlankerWindow)
  685.   {
  686.    GT_SetGadgetAttrs (BlankerGadgets[GID_TIMEOUT],BlankerWindow,NULL,
  687.                       GTIN_Number,TimeOut,TAG_DONE);
  688.    GT_SetGadgetAttrs (BlankerGadgets[GID_CLIENT],BlankerWindow,NULL,
  689.                       GTIN_Number,ClientTimeOut,TAG_DONE);
  690.  
  691.    GT_SetGadgetAttrs (BlankerGadgets[GID_MODE],BlankerWindow,NULL,
  692.                       GTLV_Selected,DisplayMode->mn_Index,TAG_DONE);
  693.  
  694.    GT_SetGadgetAttrs (BlankerGadgets[GID_MOUSE],BlankerWindow,NULL,
  695.                       GTCY_Active,MouseBlank,TAG_DONE);
  696.  
  697.    GT_SetGadgetAttrs (BlankerGadgets[GID_POPKEY],BlankerWindow,NULL,
  698.                       GTST_String,PopKey,TAG_DONE);
  699.    GT_SetGadgetAttrs (BlankerGadgets[GID_BLANKKEY],BlankerWindow,NULL,
  700.                       GTST_String,BlankKey,TAG_DONE);
  701.  
  702.    GT_SetGadgetAttrs (BlankerGadgets[GID_CHANGE],BlankerWindow,NULL,
  703.                       GTSL_Level,Change,TAG_DONE);
  704.  
  705.    GT_SetGadgetAttrs (BlankerGadgets[GID_TRAIL],BlankerWindow,NULL,
  706.                       GTSL_Level,Trail,TAG_DONE);
  707.  
  708.    GT_SetGadgetAttrs (BlankerGadgets[GID_CYCLE],BlankerWindow,NULL,
  709.                       GTCB_Checked,Cycle,TAG_DONE);
  710.   }
  711.  
  712.  if (DiskObject) FreeDiskObject (DiskObject);
  713. }
  714.  
  715. void REGARGS SaveConfig(char *Name)
  716.  
  717. {
  718.  struct DiskObject *DiskObject;
  719.  ULONG Index;
  720.  char **NewToolTypes,**NextEntry,**OldToolTypes;
  721.  
  722.  if ((DiskObject=GetDiskObjectNew(Name))==NULL)
  723.   {
  724.    DisplayBeep (BlankerWindow->WScreen);
  725.    return;
  726.   }
  727.  
  728.  Index=0L;
  729.  OldToolTypes=DiskObject->do_ToolTypes;
  730.  while (OldToolTypes[Index]) Index++;
  731.  Index+=NUMTOOLTYPES+1L;
  732.  
  733.  if ((NewToolTypes=(char **)AllocVec(Index*4L+NUMTOOLTYPES*48L,
  734.                                      MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  735.   {
  736.    FreeDiskObject (DiskObject);
  737.    return;
  738.   }
  739.  NextEntry=NewToolTypes;
  740.  
  741.  SPrintF (*NextEntry++=(char *)&NewToolTypes[Index],"%s=%ld",ToolTypeIDs[0],
  742.                                                     CxPri);
  743.  SPrintF (*NextEntry++=NewToolTypes[0]+48L,"%s=NO",ToolTypeIDs[1]);
  744.  SPrintF (*NextEntry++=NewToolTypes[1]+48L,"%s=%s",ToolTypeIDs[2],PopKey);
  745.  SPrintF (*NextEntry++=NewToolTypes[2]+48L,"%s=%s",ToolTypeIDs[3],BlankKey);
  746.  SPrintF (*NextEntry++=NewToolTypes[3]+48L,"%s=%ld",ToolTypeIDs[4],TimeOut);
  747.  SPrintF (*NextEntry++=NewToolTypes[4]+48L,"%s=%ld",ToolTypeIDs[5],
  748.           ClientTimeOut);
  749.  SPrintF (*NextEntry++=NewToolTypes[5]+48L,"%s=%s",ToolTypeIDs[6],
  750.           DisplayMode->mn_Name);
  751.  SPrintF (*NextEntry++=NewToolTypes[6]+48L,"%s=%s",ToolTypeIDs[7],
  752.           MouseBlankMethods[MouseBlank]);
  753.  SPrintF (*NextEntry++=NewToolTypes[7]+48L,"%s=%ld",ToolTypeIDs[8],Change);
  754.  SPrintF (*NextEntry++=NewToolTypes[8]+48L,"%s=%ld",ToolTypeIDs[9],Trail);
  755.  SPrintF (*NextEntry++=NewToolTypes[9]+48L,"%s=%s",ToolTypeIDs[10],
  756.           YesNo(Cycle));
  757.  
  758.  
  759.  Index=0L;
  760.  while (OldToolTypes[Index])
  761.   {
  762.    char *Ptr,*Asgn;
  763.  
  764.    if (Ptr=(char *)AllocVec(strlen(OldToolTypes[Index])+1L,0L))
  765.     {
  766.      if (Asgn=strchr(strcpy(Ptr,OldToolTypes[Index]),'=')) *Asgn='\0';
  767.      if (FindToolType(NewToolTypes,Ptr)==NULL) *NextEntry++=OldToolTypes[Index];
  768.      FreeVec ((APTR)Ptr);
  769.     }
  770.    Index++;
  771.   }
  772.  
  773.  DiskObject->do_ToolTypes=NewToolTypes;
  774.  if (!PutDiskObject(Name,DiskObject)) DisplayBeep (BlankerWindow->WScreen);
  775.  DiskObject->do_ToolTypes=OldToolTypes;
  776.  
  777.  FreeVec ((APTR)NewToolTypes);
  778.  FreeDiskObject (DiskObject);
  779. }
  780.  
  781. /*
  782.  
  783.    Our "InputHandler"
  784.  
  785. */
  786.  
  787. VOID_INTERRUPT BlankerAction(CxMsg *CxMsg,CxObj *CO)
  788.  
  789. {
  790.  struct InputEvent *IE;
  791.  
  792.  IE=(struct InputEvent *)CxMsgData(CxMsg);
  793.  if (IE->ie_Class==IECLASS_TIMER)
  794.   {
  795.    if (TimeLeft)
  796.     {
  797.      TimeLeft--;
  798.      if (TimeLeft==0L) Signal (BlankerServerProcess,1L<<bsp_TimeOut);
  799.     }
  800.   }
  801.  else
  802.   {
  803.    Signal (BlankerServerProcess,1L<<bsp_InputSig);
  804.    TimeLeft=InitTimeLeft;
  805.   }
  806. }
  807.  
  808. /*
  809.  
  810.    Functions for Handling the Configuration Window
  811.  
  812. */
  813.  
  814. LONG GetNum(struct Gadget *Gadget,LONG *Data,LONG Max)
  815.  
  816. {
  817.  LONG NewData;
  818.  
  819.  NewData=((struct StringInfo *)Gadget->SpecialInfo)->LongInt;
  820.  if ((NewData<1L)||(NewData>Max))
  821.   {
  822.    GT_SetGadgetAttrs (Gadget,BlankerWindow,NULL,GTIN_Number,(ULONG)*Data,
  823.                       TAG_DONE);
  824.    return FALSE;
  825.   }
  826.  else
  827.   {
  828.    *Data=NewData;
  829.    return TRUE;
  830.   }
  831. }
  832.  
  833. void CloseBlankerWindow(void)
  834.  
  835. {
  836.  if (BlankerContext)
  837.   {
  838.    if (BlankerWindow)
  839.     {
  840.      LeftEdge=BlankerWindow->LeftEdge;
  841.      TopEdge=BlankerWindow->TopEdge;
  842.      ClearMenuStrip (BlankerWindow);
  843.      if (BlankerVisualInfo)
  844.       {
  845.        FreeVisualInfo (BlankerVisualInfo);
  846.        BlankerVisualInfo=NULL;
  847.        if (BlankerMenu)
  848.         {
  849.          FreeMenus (BlankerMenu);
  850.          BlankerMenu=NULL;
  851.         }
  852.       }
  853.      CloseWindow (BlankerWindow);
  854.      BlankerWindow=NULL;
  855.     }
  856.    FreeGadgets (BlankerContext);
  857.    BlankerContext=NULL;
  858.   }
  859. }
  860.  
  861. void OpenBlankerWindow(void)
  862.  
  863. {
  864.  struct Gadget *Ptr;
  865.  UWORD Index;
  866.  
  867.  if (BlankerWindow==NULL)
  868.   {
  869.    struct NewGadget NewGadget;
  870.  
  871.    BlankerContext=NULL;
  872.    if ((Ptr=CreateContext(&BlankerContext))==NULL) return;
  873.  
  874.    if ((BlankerWindow=OpenWindowTags(NULL,
  875.                                      WA_Left,LeftEdge,
  876.                                      WA_Top,TopEdge,
  877.                                      WA_IDCMP,IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW|
  878.                                       IDCMP_VANILLAKEY|IDCMP_MENUPICK|LISTVIEWIDCMP,
  879.                                      WA_Flags,WFLG_DRAGBAR|WFLG_DEPTHGADGET|
  880.                                       WFLG_CLOSEGADGET|WFLG_SIMPLE_REFRESH|
  881.                                       WFLG_NEWLOOKMENUS,
  882.                                      WA_Title,
  883.                                       (ULONG)"Rotor V1.01 © 1993 by Illenseer",
  884.                                      WA_AutoAdjust,TRUE,
  885.                                      WA_InnerWidth,512,
  886.                                      WA_InnerHeight,117L,TAG_DONE))==NULL)
  887.     {
  888.      CloseBlankerWindow();
  889.      return;
  890.     }
  891.  
  892.    if ((BlankerVisualInfo=GetVisualInfo(BlankerWindow->WScreen,TAG_DONE))==NULL)
  893.     {
  894.      CloseBlankerWindow();
  895.      return;
  896.     }
  897.  
  898.    if (!WBStarted)
  899.     {
  900.      NewBlankerMenus[1].nm_Flags|=NM_ITEMDISABLED;
  901.      NewBlankerMenus[2].nm_Flags|=NM_ITEMDISABLED;
  902.     }
  903.    if ((BlankerMenu=CreateMenus(NewBlankerMenus,
  904.                                 GTMN_FullMenu,TRUE,
  905.                                 TAG_DONE))==NULL)
  906.     {
  907.      CloseBlankerWindow();
  908.      return;
  909.     }
  910.    if (!LayoutMenus(BlankerMenu,BlankerVisualInfo,
  911.                     GTMN_NewLookMenus,TRUE,TAG_DONE))
  912.     {
  913.      CloseBlankerWindow();
  914.      return;
  915.     }
  916.    else SetMenuStrip (BlankerWindow,BlankerMenu);
  917.  
  918.    BlankerGadgetTags[0].ti_Data=(ULONG)ModeList;
  919.    BlankerGadgetTags[1].ti_Data=(ULONG)DisplayMode->mn_Index;
  920.    BlankerGadgetTags[4].ti_Data=(ULONG)TimeOut;
  921.    BlankerGadgetTags[7].ti_Data=(ULONG)ClientTimeOut;
  922.    BlankerGadgetTags[13].ti_Data=(ULONG)PopKey;
  923.    BlankerGadgetTags[16].ti_Data=(ULONG)BlankKey;
  924.    BlankerGadgetTags[10].ti_Data=(ULONG)&MouseBlankMethods[0];
  925.    BlankerGadgetTags[11].ti_Data=(ULONG)MouseBlank;
  926.    BlankerGadgetTags[21].ti_Data=(ULONG)Change;
  927.    BlankerGadgetTags[29].ti_Data=(ULONG)Trail;
  928.    BlankerGadgetTags[35].ti_Data=(ULONG)Cycle;
  929.  
  930.    for (Index=0L; Index<NUM_GADS; Index++)
  931.     {
  932.      NewGadget=NewBlankerGadgets[Index];
  933.      NewGadget.ng_TopEdge+=BlankerWindow->BorderTop;
  934.      NewGadget.ng_VisualInfo=BlankerVisualInfo;
  935.      Ptr=CreateGadget((ULONG)BlankerGadgetKinds[Index],Ptr,&NewGadget,
  936.                       GT_Underscore,(ULONG)'_',TAG_MORE,
  937.                       &BlankerGadgetTags[BlankerTagsIndex[Index]]);
  938.      if ((BlankerGadgets[Index]=Ptr)==NULL)
  939.       {
  940.        CloseBlankerWindow();
  941.        return;
  942.       }
  943.     }
  944.  
  945.    AddGList (BlankerWindow,BlankerContext,0L,-1L,NULL);
  946.    RefreshGadgets (BlankerContext,BlankerWindow,NULL);
  947.    GT_RefreshWindow (BlankerWindow,NULL);
  948.   }
  949.  
  950.  ScreenToFront (BlankerWindow->WScreen);
  951.  WindowToFront (BlankerWindow);
  952.  ActivateWindow (BlankerWindow);
  953. }
  954.  
  955. void About(void)
  956.  
  957. {
  958.  ULONG IDCMPFlags;
  959.  
  960.  IDCMPFlags=0L;
  961.  (void)EasyRequestArgs(NULL,&AboutEasyStruct,&IDCMPFlags,NULL);
  962. }
  963.  
  964. /*
  965.  
  966.    Function to handle the Commodity Stuff
  967.  
  968. */
  969.  
  970. void REGARGS HandleCxMsg(CxMsg *CxMsg)
  971.  
  972. {
  973.  ULONG MsgType,MsgID;
  974.  
  975.  MsgType=CxMsgType(CxMsg);
  976.  MsgID=CxMsgID(CxMsg);
  977.  ReplyMsg ((struct Message *)CxMsg);
  978.  
  979.  switch (MsgType)
  980.   {
  981.    case CXM_IEVENT: /* PopKey was pressed */
  982.     if (MsgID==EVENT_BLANK) InitTimeLeft=2L;
  983.     else OpenBlankerWindow();
  984.     break;
  985.    case CXM_COMMAND:
  986.     switch (MsgID)
  987.      {
  988.       case CXCMD_DISABLE:
  989.        /* Message created by Exchange (except CXCMD_UNIQUE) */
  990.        (void)ActivateCxObj(Broker,FALSE);
  991.        break;
  992.       case CXCMD_ENABLE:
  993.        (void)ActivateCxObj(Broker,TRUE);
  994.        break;
  995.       case CXCMD_UNIQUE:
  996.       case CXCMD_APPEAR:
  997.        OpenBlankerWindow();
  998.        break;
  999.       case CXCMD_DISAPPEAR:
  1000.        CloseBlankerWindow();
  1001.        break;
  1002.       case CXCMD_KILL:
  1003.        exit (0);
  1004.      }
  1005.    }
  1006. }
  1007.  
  1008. CxObj REGARGS *InstallHotKey(CxObj *Filter,char *Describ,LONG Event,
  1009.                              char *Default)
  1010.  
  1011. {
  1012.  if (Filter)
  1013.   {
  1014.    RemoveCxObj (Filter);
  1015.    DeleteCxObj (Filter);
  1016.   }
  1017.  
  1018.  if (Filter=HotKey(Describ,CxPort,Event))
  1019.   if (CxObjError(Filter)==0L)
  1020.    {
  1021.     AttachCxObj (Broker,Filter);
  1022.     return Filter;
  1023.    }
  1024.   else DeleteCxObj (Filter);
  1025.  
  1026.  if (Filter=HotKey(Default,CxPort,Event))
  1027.   if (CxObjError(Filter)==0L)
  1028.    {
  1029.     AttachCxObj (Broker,Filter);
  1030.     (void)strcpy(Describ,Default);
  1031.     return Filter;
  1032.    }
  1033.   else DeleteCxObj (Filter);
  1034.  
  1035.  (void)strcpy(Describ,"<NONE>");
  1036.  return NULL;
  1037. }
  1038.  
  1039. /*
  1040.  
  1041.    Functions fore Creating/Deleting the Client Process
  1042.  
  1043. */
  1044.  
  1045. VOID_STDARGS DeleteBlankerClient(struct MsgPort *BlankerClientPort,
  1046.                                  struct BlankerClientMsg *BlankerClientMsg)
  1047.  
  1048. {
  1049.  Forbid();
  1050.  PutMsg (BlankerClientPort,(struct Message *)BlankerClientMsg);
  1051.  (void)SetTaskPri(BlankerClientPort->mp_SigTask,SERVER_PRI+1L);
  1052.  Permit();
  1053.  
  1054.  (void)WaitPort(BlankerClientMsg->bcm_Message.mn_ReplyPort);
  1055.  (void)GetMsg(BlankerClientMsg->bcm_Message.mn_ReplyPort);
  1056. }
  1057.  
  1058. struct MsgPort *REGARGS CreateBlankerClient(void *CodePtr,
  1059.                                      struct BlankerClientMsg *BlankerClientMsg)
  1060.  
  1061. {
  1062.  struct Process *BlankerClientProcess;
  1063.  
  1064.  if (BlankerClientProcess=CreateNewProcTags(NP_Entry,CodePtr,
  1065.                                             NP_Name,"Rotor_BlankerClient",
  1066.                                             NP_StackSize,4000L,TAG_DONE))
  1067.   {
  1068.    PutMsg (&BlankerClientProcess->pr_MsgPort,
  1069.            (struct Message *)BlankerClientMsg);
  1070.  
  1071.    (void)WaitPort(BlankerClientMsg->bcm_Message.mn_ReplyPort);
  1072.    (void)GetMsg(BlankerClientMsg->bcm_Message.mn_ReplyPort);
  1073.  
  1074.    (void)SetTaskPri((struct Task *)BlankerClientProcess,CLIENT_PRI);
  1075.  
  1076.    if (BlankerClientMsg->bcm_Status) return &BlankerClientProcess->pr_MsgPort;
  1077.   }
  1078.  return NULL;
  1079. }
  1080.  
  1081. /*
  1082.  
  1083.    Open a Screen with the supplied DisplayID
  1084.  
  1085. */
  1086.  
  1087. void SpritesOff(void)
  1088.  
  1089. {
  1090.  ULONG Index;
  1091.  
  1092.  if (MouseBlank)
  1093.   {
  1094.    FreeSprite (0); /* hack required for DOMINO-Gfx-Board */
  1095.    GfxBase->SpriteReserved|=1;
  1096.   }
  1097.  else
  1098.   {
  1099.    OFF_SPRITE /* switch sprites off */
  1100.    for (Index=0L; Index<8L; Index++) custom.spr[Index].ctl=0;
  1101.   }
  1102. }
  1103.  
  1104. struct Screen *CreateScreen(struct List *ModeList,struct ModeNode *ModeNode)
  1105.  
  1106. {
  1107.  struct Screen *Screen;
  1108.  
  1109.  if (Screen=OpenScreenTags(NULL,
  1110.                            SA_Depth,1,
  1111.                            SA_Title,"Rotor",
  1112.                            SA_DisplayID,ModeNode->mn_DisplayID,
  1113.                            SA_Quiet,TRUE,TAG_DONE))
  1114.   {
  1115.    SetRGB4 (&Screen->ViewPort,0,0,0,0);
  1116.    SetRast (&Screen->RastPort,0);
  1117.  
  1118.    SpritesOff();
  1119.   }
  1120.  return Screen;
  1121. }
  1122.  
  1123. /*
  1124.  
  1125.    Functions for Creating/Drawing/Removing the Gfx
  1126.  
  1127. */
  1128.  
  1129. /* Ill's strange and genius Random Function :-) */
  1130.  
  1131. UWORD REGARGS Random(UWORD Max)
  1132.  
  1133. {
  1134.  static ULONG Num=0L; /* So the last random-number is still stored ! */
  1135.  ULONG Sec,Mic;
  1136.  
  1137.  CurrentTime((LONG *)&Sec,(LONG *)&Mic);
  1138.  
  1139.  Num*=Sec;
  1140.  Num+=Mic;
  1141.  
  1142.  while (Num>32767L) Num=Num>>1;
  1143.  
  1144.  return (UWORD)(Num%Max);
  1145. }
  1146.  
  1147. ULONG RotorSize(LONG elems)
  1148. {
  1149.  return sizeof(struct flightstruct);
  1150. }
  1151.  
  1152. struct flightstruct *REGARGS CreateRotor(struct Screen *RotorScreen,int Trail)
  1153. /* allocate Memory and such */
  1154. {
  1155.  flightstruct *fs;  /* !!!!!!!!!!!!!! */
  1156.  int         x;
  1157.  struct elem *pelem;
  1158.  
  1159.  if((fs=AllocVec(RotorSize(DEFAULTCOUNT),MEMF_ANY | MEMF_CLEAR))==NULL) return NULL;
  1160.  
  1161.  fs->centerx = (RotorScreen->Width / 2);
  1162.  fs->centery = (RotorScreen->Height / 2);
  1163.  fs->firsttime = TRUE;
  1164.  fs->height=RotorScreen->Height;
  1165.  fs->width=RotorScreen->Width;
  1166.  fs->smallscreen = fs->width < 320; /* Oops ? Screenmode below LowRes ? */
  1167.  fs->num = DEFAULTCOUNT;
  1168.  fs->Trail = Trail;
  1169.  
  1170.  if (fs->elements == NULL) {
  1171.   if ((fs->elements = (struct elem *) malloc(sizeof(struct elem) * fs->num)) == NULL) {
  1172.   exit (10);
  1173.   }
  1174.  }
  1175.  
  1176.  if (fs->savex == NULL) {
  1177.   if ((fs->savex= (int *) calloc(sizeof(int) , Trail)) == NULL) {
  1178.   exit (10);
  1179.   }
  1180.  }
  1181.  
  1182.  if (fs->savey == NULL) {
  1183.   if ((fs->savey= (int *) calloc(sizeof(int) , Trail)) == NULL) {
  1184.   exit (10);
  1185.   }
  1186.  }
  1187.  
  1188.  pelem = fs->elements;
  1189.  
  1190.  for (x = fs->num; --x >= 0; pelem++) {
  1191.     pelem->radius_drift_max = 1.0;
  1192.     pelem->radius_drift_now = 1.0;
  1193.  
  1194.     pelem->end_radius = fs->height/5.0;
  1195.  
  1196.     pelem->ratio_drift_max = 1.0;
  1197.     pelem->ratio_drift_now = 1.0;
  1198.     pelem->end_ratio = 10.0;
  1199.  }
  1200.  
  1201.  fs->rotor = 0;
  1202.  fs->prev = 1;
  1203.  fs->lastx = fs->centerx;
  1204.  fs->lasty = fs->centery;
  1205.  fs->angle = (float)(Random(MAXANGLE)) / 3;
  1206.  fs->forward = fs->firsttime = TRUE;
  1207.  
  1208.  return fs;
  1209.  
  1210. }
  1211.  
  1212. void REGARGS DrawRotor(struct RastPort *RP,struct flightstruct *fs)
  1213. {
  1214.     register struct elem *pelem;
  1215.     int         thisx,
  1216.                 thisy;
  1217.     int         i,
  1218.                 rp;
  1219.     int         x1,
  1220.                 y1,
  1221.                 x2,
  1222.                 y2;
  1223.  
  1224. #define CAT(X,Y)    X##Y
  1225. #define SCALE(W,N)    CAT(W,N)=(CAT(fs->center,W)) +((CAT(W,N) - CAT(fs->center,W))/2)
  1226. #define SCALEIFSMALL()    if (fs->smallscreen) {     \
  1227.                               SCALE(x,1); SCALE(x,2);    \
  1228.                   SCALE(y,1); SCALE(y,2);    \
  1229.               }
  1230.  
  1231.  for (rp = 0; rp < REPS; rp++) {
  1232.   thisx = fs->centerx;
  1233.   thisy = fs->centery;
  1234.  
  1235.   for (i = fs->num, pelem = fs->elements; --i >= 0; pelem++) {
  1236.       if (pelem->radius_drift_max <= pelem->radius_drift_now) {
  1237.         pelem->start_radius     = pelem->end_radius;
  1238.         pelem->end_radius       = (float) (Random(40000)) / 100.0 - 200.0;
  1239.         pelem->radius_drift_max = (float) (Random(65375)+Random(34464)) + 10000.0;
  1240.         pelem->radius_drift_now = 0.0;
  1241.       }
  1242.       if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
  1243.         pelem->start_ratio     = pelem->end_ratio;
  1244.         pelem->end_ratio       = (float) (Random(2000)) / 100.0 - 10.0;
  1245.         pelem->ratio_drift_max = (float) (Random(65375)+Random(34464)) + 10000.0;
  1246.         pelem->ratio_drift_now = 0.0;
  1247.       }
  1248.       pelem->ratio = pelem->start_ratio + (pelem->end_ratio - pelem->start_ratio) /
  1249.                      pelem->ratio_drift_max * pelem->ratio_drift_now;
  1250.       pelem->angle = fs->angle * pelem->ratio;
  1251.       pelem->radius = pelem->start_radius + (pelem->end_radius - pelem->start_radius) /
  1252.                       pelem->radius_drift_max * pelem->radius_drift_now;
  1253.  
  1254.       thisx += (int) (cos(pelem->angle) * pelem->radius);
  1255.       thisy += (int) (sin(pelem->angle) * pelem->radius);
  1256.  
  1257.       if (thisx<BORDER) thisx=BORDER;
  1258.       if (thisx>fs->width-BORDER-1) thisx=fs->width-BORDER-1;
  1259.       if (thisy<BORDER) thisy=BORDER;
  1260.       if (thisy>fs->height-BORDER-1) thisy=fs->height-BORDER-1;
  1261.  
  1262.       pelem->ratio_drift_now += 1.0;
  1263.       pelem->radius_drift_now += 1.0;
  1264.   }
  1265.   if (fs->firsttime)
  1266.       fs->firsttime = FALSE;
  1267.   else {
  1268.  
  1269.       x1 = (int) fs->savex[fs->rotor];
  1270.       y1 = (int) fs->savey[fs->rotor];
  1271.       x2 = (int) fs->savex[fs->prev];
  1272.       y2 = (int) fs->savey[fs->prev];
  1273.  
  1274.       SCALEIFSMALL();
  1275.  
  1276.       SetAPen(RP,0);
  1277.  
  1278.       Move(RP,x1, y1);
  1279.       Draw(RP,x2, y2);
  1280.  
  1281.       x1 = fs->lastx;
  1282.       y1 = fs->lasty;
  1283.       x2 = thisx;
  1284.       y2 = thisy;
  1285.  
  1286.       SCALEIFSMALL();
  1287.  
  1288.       SetAPen(RP,1);
  1289.  
  1290.       Move(RP,x1, y1);
  1291.       Draw(RP,x2, y2);
  1292.  
  1293.   }
  1294.   fs->savex[fs->rotor] = fs->lastx = thisx;
  1295.   fs->savey[fs->rotor] = fs->lasty = thisy;
  1296.  
  1297.   ++fs->rotor;
  1298.   fs->rotor %= Trail;
  1299.   ++fs->prev;
  1300.   fs->prev %= Trail;
  1301.   if (fs->forward) {
  1302.       fs->angle += 0.01;
  1303.       if (fs->angle >= MAXANGLE) {
  1304.        fs->angle = MAXANGLE;
  1305.        fs->forward = FALSE;
  1306.       }
  1307.   }
  1308.   else {
  1309.      fs->angle -= 0.1;
  1310.      if (fs->angle <= 0) {
  1311.       fs->angle = 0.0;
  1312.       fs->forward = TRUE;
  1313.      }
  1314.   }
  1315.  }
  1316. }
  1317.  
  1318. /*
  1319.  
  1320.    This is the Client Process's Main Loop
  1321.  
  1322. */
  1323.  
  1324. VOID_INTERRUPT RotorClientProcess(void)
  1325.  
  1326. {
  1327.  struct BlankerClientMsg *BlankerClientMsg;
  1328.  struct MsgPort *BlankerClientPort;
  1329.  struct Task *BlankerServerTask;
  1330.  ULONG BlankerServerSigMask;
  1331.  struct Screen *RotorScreen;
  1332.  struct flightstruct *fs;
  1333.  LONG Change,Trail,Cycle;
  1334.  WORD Color,DColor;
  1335.  WORD Count;
  1336.  
  1337.  /* wait for Server's initial Message */
  1338.  
  1339.  BlankerClientPort=FINDPROCPORT;
  1340.  (void)WaitPort(BlankerClientPort);
  1341.  BlankerClientMsg=(struct BlankerClientMsg *)GetMsg(BlankerClientPort);
  1342.  
  1343.  BlankerServerTask=BlankerClientMsg->bcm_Message.mn_ReplyPort->mp_SigTask;
  1344.  BlankerServerSigMask=BlankerClientMsg->bcm_SigMask;
  1345.  
  1346.  Change=BlankerClientMsg->bcm_Change;
  1347.  Trail=BlankerClientMsg->bcm_Trail;
  1348.  Cycle=BlankerClientMsg->bcm_Cycle;
  1349.  
  1350.  RotorScreen=BlankerClientMsg->bcm_Screen;
  1351.  
  1352.  if ((fs=CreateRotor(RotorScreen,Trail))==NULL)
  1353.   {
  1354.    BlankerClientMsg->bcm_Status=FALSE;
  1355.    Forbid();
  1356.    ReplyMsg ((struct Message *)BlankerClientMsg);
  1357.    return;
  1358.   }
  1359.  BlankerClientMsg->bcm_Status=TRUE;
  1360.  ReplyMsg ((struct Message *)BlankerClientMsg);
  1361.  
  1362.  Color=ROTOR_COL_NUM-1;
  1363.  DColor=Cycle?1:0;
  1364.  Count=1;
  1365.  
  1366.  while ((BlankerClientMsg=(struct BlankerClientMsg *)
  1367.                            GetMsg(BlankerClientPort))==NULL)
  1368.   {
  1369.  
  1370.    /* Color Cycling */
  1371.  
  1372.    Colors[1]=RotorColors[Color];
  1373.    LoadRGB4 (&RotorScreen->ViewPort,Colors,4);
  1374.    Color+=DColor;
  1375.    if ((Color==-1)||(Color==ROTOR_COL_NUM))
  1376.     {
  1377.      DColor=-DColor;
  1378.      Color+=2*DColor;
  1379.     }
  1380.    if(Count++>Change) {
  1381.     fs->rotor = 0;
  1382.     fs->prev = 1;
  1383.     fs->lastx = fs->centerx;
  1384.     fs->lasty = fs->centery;
  1385.     fs->angle = (float)(Random(MAXANGLE)) / 3;
  1386.     fs->forward = fs->firsttime = TRUE;
  1387.     Count=0;
  1388.     SetRast(&RotorScreen->RastPort,0);
  1389.    }
  1390.    DrawRotor(&RotorScreen->RastPort,fs);
  1391.    if (IntuitionBase->FirstScreen!=RotorScreen)
  1392.     {
  1393.      ScreenToFront (RotorScreen);
  1394.      SpritesOff();
  1395.     }
  1396.    Signal (BlankerServerTask,BlankerServerSigMask);
  1397.   }
  1398.  FreeVec ((APTR)fs);
  1399.  
  1400.  /* We are requested to finish, so we do. */
  1401.  
  1402.  Forbid();
  1403.  ReplyMsg ((struct Message *)BlankerClientMsg);
  1404. }
  1405.  
  1406. /*
  1407.  
  1408.    The Main Loop
  1409.  
  1410. */
  1411.  
  1412. void main(LONG argc,UBYTE **argv)
  1413.  
  1414. {
  1415.  CxObj *ObjectList;
  1416.  struct IntuiMessage *IntMsg;
  1417.  CxMsg *BlankerCxMsg;
  1418.  struct Screen *BlankerScreen=NULL;
  1419.  struct MsgPort *BlankerClientPort=NULL;
  1420.  
  1421.  /* open our Libraries */
  1422.  
  1423.  AddTool (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L),
  1424.           CloseLibrary,0L);
  1425.  AddTool (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",
  1426.           37L),CloseLibrary,0L);
  1427.  AddTool (CxBase=OpenLibrary("commodities.library",37L),CloseLibrary,0L);
  1428.  AddTool (GadToolsBase=OpenLibrary("gadtools.library",37L),CloseLibrary,0L);
  1429.  
  1430.  /* create List of Graphics Modes */
  1431.  
  1432.  AddTool (ModeList=CreateModeList(),DeleteModeList,0L);
  1433.  
  1434.  /* get some Signals */
  1435.  
  1436.  BlankerServerProcess=SysBase->ThisTask;
  1437.  if ((bsp_TimeOut=AllocSignal(-1L))==-1) exit (10);
  1438.  AddTool ((void *)bsp_TimeOut,FreeSignal,0L);
  1439.  if ((bsp_InputSig=AllocSignal(-1L))==-1) exit (10);
  1440.  AddTool ((void *)bsp_InputSig,FreeSignal,0L);
  1441.  if ((bsp_ClientSig=AllocSignal(-1L))==-1) exit (10);
  1442.  AddTool ((void *)bsp_ClientSig,FreeSignal,0L);
  1443.  
  1444.  /* Were we started from Workbench or from CLI ? */
  1445.  
  1446.  if (WBStarted=(argc==0L))
  1447.   {
  1448.    /* Workbench: load Config from DiskObject */
  1449.    struct WBStartup *WBenchMsg;
  1450.  
  1451.    AddTool (IconBase=OpenLibrary(ICONNAME,37L),CloseLibrary,0L);
  1452.  
  1453.    WBenchMsg=(struct WBStartup *)argv;
  1454.    LoadConfig (WBenchMsg->sm_NumArgs?WBenchMsg->sm_ArgList->wa_Name:NULL);
  1455.   }
  1456.  else
  1457.   {
  1458.    struct RDArgs *RDArgs;
  1459.    LONG Array[NUMTOOLTYPES];
  1460.  
  1461.    (void)memset(Array,'\0',sizeof(Array));
  1462.    if (RDArgs=ReadArgs(Template,Array,NULL))
  1463.     {
  1464.      AddTool (RDArgs,FreeArgs,0L);
  1465.  
  1466.      CxPri=RDArgsLong(Array[0],0L,-128L,127L);
  1467.      (void)strcpy(PopKey,Array[1]?(char *)Array[1]:DEF_POPKEY);
  1468.      CxPopUp=Array[2];
  1469.      (void)strcpy(BlankKey,Array[3]?(char *)Array[3]:DEF_BLANKKEY);
  1470.  
  1471.      /* get Time Out, Client Time Out and Display mode */
  1472.  
  1473.      TimeOut=RDArgsLong(Array[4],DEF_TIMEOUT,1L,MAX_TIMEOUT);
  1474.      ClientTimeOut=RDArgsLong(Array[5],DEF_CLIENT_TIMEOUT,1L,
  1475.                    MAX_CLIENT_TIMEOUT);
  1476.      if ((DisplayMode=FindMode(ModeList,Array[6]?(char *)Array[6]:""))==NULL)
  1477.       DisplayMode=GetDefaultMode(ModeList);
  1478.  
  1479.      if (stricmp(Array[7]?(char *)Array[7]:"",MouseBlankMethods[1]))
  1480.       MouseBlank=0L;
  1481.      else MouseBlank=1L;
  1482.  
  1483.      Change=RDArgsLong(Array[8],DEF_CHANGE,1L,MAX_CHANGE);
  1484.      Trail=RDArgsLong(Array[9],DEF_TRAIL,1L,MAX_TRAIL);
  1485.      Cycle=Array[10];
  1486.  
  1487.     }
  1488.    else
  1489.     {
  1490.      PrintFault (IoErr(),"Rotor");
  1491.      exit (10);
  1492.     }
  1493.   }
  1494.  
  1495.  /* initialize our Broker=install us as a Commodity */
  1496.  
  1497.  AddTool (CxPort=CreateMsgPort(),DeleteMsgPortSafely,0L);
  1498.  
  1499.  NewBroker.nb_Pri=(BYTE)CxPri;
  1500.  NewBroker.nb_Port=CxPort;
  1501.  AddTool (Broker=CxBroker(&NewBroker,NULL),DeleteCxObjAll,0L);
  1502.  
  1503.  /* install our Hot Keys */
  1504.  
  1505.  PopKeyFilter=InstallHotKey(NULL,PopKey,EVENT_OPEN_WINDOW,DEF_POPKEY);
  1506.  BlankKeyFilter=InstallHotKey(NULL,BlankKey,EVENT_BLANK,DEF_BLANKKEY);
  1507.  
  1508.  /* install our "InputHandler" */
  1509.  
  1510.  TimeLeft=InitTimeLeft=TimeOut*10L;
  1511.  ObjectList=CxCustom(BlankerAction,0L);
  1512.  AttachCxObj (Broker,ObjectList);
  1513.  if (CxObjError(ObjectList)) exit (10);
  1514.  
  1515.  (void)ActivateCxObj(Broker,TRUE);
  1516.  AddTool (Broker,ActivateCxObj,FALSE);
  1517.  
  1518.  /* open Window on startup if not forbidden */
  1519.  
  1520.  AddTool ((void *)-1L,CloseBlankerWindow,0L);
  1521.  if (CxPopUp) OpenBlankerWindow();
  1522.  
  1523.  /* increase our Priority */
  1524.  
  1525.  AddTool (FindTask(NULL),SetTaskPri,(LONG)SetTaskPri(FindTask(NULL),
  1526.                          SERVER_PRI));
  1527.  
  1528.  /* start the Loop */
  1529.  
  1530.  FOREVER
  1531.   {
  1532.    ULONG Mask;
  1533.  
  1534.    if (BlankerWindow)
  1535.     Mask=Wait(MASK(bsp_TimeOut)|MASK(bsp_InputSig)|MASK(bsp_ClientSig)|
  1536.               MASK(CxPort->mp_SigBit)|MASK(BlankerWindow->UserPort->mp_SigBit)|
  1537.               SIGBREAKF_CTRL_C);
  1538.    else
  1539.     Mask=Wait(MASK(bsp_TimeOut)|MASK(bsp_InputSig)|MASK(bsp_ClientSig)|
  1540.               MASK(CxPort->mp_SigBit)|SIGBREAKF_CTRL_C);
  1541.  
  1542.    /* process Window Events */
  1543.  
  1544.    while ((BlankerWindow!=NULL)&&(IntMsg=GT_GetIMsg(BlankerWindow->UserPort)))
  1545.     switch (IntMsg->Class)
  1546.      {
  1547.       struct Gadget *Clicked;
  1548.       UWORD Code;
  1549.  
  1550.       case IDCMP_CLOSEWINDOW:
  1551.        GT_ReplyIMsg (IntMsg);
  1552.        CloseBlankerWindow();
  1553.        break;
  1554.       case IDCMP_REFRESHWINDOW:
  1555.        GT_BeginRefresh (BlankerWindow);
  1556.        GT_EndRefresh (BlankerWindow,TRUE);
  1557.        break;
  1558.       case IDCMP_GADGETUP:
  1559.        Code=IntMsg->Code;
  1560.        Clicked=(struct Gadget *)IntMsg->IAddress;
  1561.        GT_ReplyIMsg (IntMsg);
  1562.        switch (Clicked->GadgetID)
  1563.         {
  1564.          case GID_HIDE:
  1565.           CloseBlankerWindow();
  1566.           break;
  1567.          case GID_QUIT:
  1568.           exit (0);
  1569.          case GID_BLANK:
  1570.           InitTimeLeft=2L;
  1571.           break;
  1572.          case GID_MODE:
  1573.           DisplayMode=GetIndexMode(ModeList,Code);
  1574.           break;
  1575.          case GID_TIMEOUT:
  1576.           if (GetNum(Clicked,&TimeOut,MAX_TIMEOUT))
  1577.            TimeLeft=InitTimeLeft=10L*TimeOut;
  1578.           break;
  1579.          case GID_CLIENT:
  1580.           GetNum(Clicked,&ClientTimeOut,MAX_CLIENT_TIMEOUT);
  1581.           break;
  1582.          case GID_MOUSE:
  1583.           MouseBlank=1L-MouseBlank;
  1584.           break;
  1585.          case GID_CHANGE:
  1586.           Change=Code;
  1587.           break;
  1588.          case GID_TRAIL:
  1589.           Trail=Code;
  1590.           break;
  1591.          case GID_POPKEY:
  1592.           (void)strcpy(PopKey,((struct StringInfo *)
  1593.                                Clicked->SpecialInfo)->Buffer);
  1594.           PopKeyFilter=InstallHotKey(PopKeyFilter,PopKey,EVENT_OPEN_WINDOW,
  1595.                                      DEF_POPKEY);
  1596.           GT_SetGadgetAttrs (Clicked,BlankerWindow,NULL,GTST_String,PopKey,
  1597.                              TAG_DONE);
  1598.           break;
  1599.          case GID_BLANKKEY:
  1600.           (void)strcpy(BlankKey,((struct StringInfo *)
  1601.                                  Clicked->SpecialInfo)->Buffer);
  1602.           BlankKeyFilter=InstallHotKey(BlankKeyFilter,BlankKey,EVENT_BLANK,
  1603.                                        DEF_BLANKKEY);
  1604.           GT_SetGadgetAttrs (Clicked,BlankerWindow,NULL,GTST_String,BlankKey,
  1605.                              TAG_DONE);
  1606.          case GID_CYCLE:
  1607.           Cycle=!Cycle;
  1608.           break;
  1609.  
  1610.         }
  1611.        break;
  1612.       case IDCMP_MENUPICK:
  1613.        Code=IntMsg->Code;
  1614.        GT_ReplyIMsg (IntMsg);
  1615.        switch (Code)
  1616.         {
  1617.          struct WBStartup *WBenchMsg;
  1618.  
  1619.          case 0xF800:
  1620.           WBenchMsg=(struct WBStartup *)argv;
  1621.           LoadConfig (WBenchMsg->sm_NumArgs?WBenchMsg->sm_ArgList->wa_Name:
  1622.                       NULL);
  1623.           PopKeyFilter=InstallHotKey(PopKeyFilter,PopKey,EVENT_OPEN_WINDOW,
  1624.                                      DEF_POPKEY);
  1625.           BlankKeyFilter=InstallHotKey(BlankKeyFilter,BlankKey,EVENT_BLANK,
  1626.                                        DEF_BLANKKEY);
  1627.           break;
  1628.          case 0xF820:
  1629.           WBenchMsg=(struct WBStartup *)argv;
  1630.           if (WBenchMsg->sm_NumArgs) SaveConfig(WBenchMsg->sm_ArgList->wa_Name);
  1631.           break;
  1632.          case 0xF860:
  1633.           About();
  1634.           break;
  1635.          case 0xF8A0:
  1636.           CloseBlankerWindow();
  1637.           break;
  1638.          case 0xF8C0:
  1639.           exit (0);
  1640.           break;
  1641.          case 0xF801:
  1642.           LoadConfig (NULL);
  1643.           PopKeyFilter=InstallHotKey(PopKeyFilter,PopKey,EVENT_OPEN_WINDOW,
  1644.                                      DEF_POPKEY);
  1645.           BlankKeyFilter=InstallHotKey(BlankKeyFilter,BlankKey,EVENT_BLANK,
  1646.                                        DEF_BLANKKEY);
  1647.         }
  1648.        break;
  1649.       case IDCMP_VANILLAKEY:
  1650.        Code=IntMsg->Code;
  1651.        GT_ReplyIMsg (IntMsg);
  1652.        switch ((char)Code)
  1653.         {
  1654.          case 'H':
  1655.          case 'h':
  1656.           CloseBlankerWindow();
  1657.           break;
  1658.          case 'Q':
  1659.          case 'q':
  1660.           exit (0);
  1661.          case 'B':
  1662.          case 'b':
  1663.           InitTimeLeft=2L;
  1664.           break;
  1665.          case 'I':
  1666.          case 'i':
  1667.           ActivateGadget (BlankerGadgets[GID_TIMEOUT],BlankerWindow,NULL);
  1668.           break;
  1669.          case 'L':
  1670.          case 'l':
  1671.           ActivateGadget (BlankerGadgets[GID_CLIENT],BlankerWindow,NULL);
  1672.           break;
  1673.          case 'P':
  1674.          case 'p':
  1675.           ActivateGadget (BlankerGadgets[GID_POPKEY],BlankerWindow,NULL);
  1676.           break;
  1677.          case 'K':
  1678.          case 'k':
  1679.           ActivateGadget (BlankerGadgets[GID_BLANKKEY],BlankerWindow,NULL);
  1680.           break;
  1681.          case 'M':
  1682.          case 'm':
  1683.           MouseBlank=1L-MouseBlank;
  1684.           GT_SetGadgetAttrs (BlankerGadgets[GID_MOUSE],BlankerWindow,
  1685.                              NULL,GTCY_Active,MouseBlank,TAG_DONE);
  1686.           break;
  1687.          case 'C':
  1688.           if (Change>1 && Change-10>1)
  1689.            {
  1690.             Change-=10;
  1691.             GT_SetGadgetAttrs (BlankerGadgets[GID_CHANGE],BlankerWindow,
  1692.                                NULL,GTSL_Level,Change,TAG_DONE);
  1693.            }
  1694.           break;
  1695.          case 'c':
  1696.           if (Change<MAX_CHANGE && Change+10<=MAX_CHANGE)
  1697.            {
  1698.             Change+=10;
  1699.             GT_SetGadgetAttrs (BlankerGadgets[GID_CHANGE],BlankerWindow,
  1700.                                NULL,GTSL_Level,Change,TAG_DONE);
  1701.            }
  1702.           break;
  1703.          case 'T':
  1704.           if (Trail>2 && Trail-10>2)
  1705.            {
  1706.             Trail-=10;
  1707.             GT_SetGadgetAttrs (BlankerGadgets[GID_TRAIL],BlankerWindow,
  1708.                                NULL,GTSL_Level,Trail,TAG_DONE);
  1709.            }
  1710.           break;
  1711.          case 't':
  1712.           if (Trail<=MAX_TRAIL && Trail+10<=MAX_TRAIL)
  1713.            {
  1714.             Trail+=10;
  1715.             GT_SetGadgetAttrs (BlankerGadgets[GID_TRAIL],BlankerWindow,
  1716.                                NULL,GTSL_Level,Trail,TAG_DONE);
  1717.            }
  1718.           break;
  1719.          case 'O':
  1720.          case 'o':
  1721.           Cycle=!Cycle;
  1722.           GT_SetGadgetAttrs (BlankerGadgets[GID_CYCLE],BlankerWindow,
  1723.                              NULL,GTCB_Checked,Cycle,TAG_DONE);
  1724.           break;
  1725.         }
  1726.        break;
  1727.       default:
  1728.        GT_ReplyIMsg (IntMsg);
  1729.      }
  1730.  
  1731.    /* process Commodity Messages */
  1732.  
  1733.    while (BlankerCxMsg=(CxMsg *)GetMsg(CxPort)) HandleCxMsg (BlankerCxMsg);
  1734.  
  1735.    /* check for <CTRL>-C */
  1736.  
  1737.    if (Mask&SIGBREAKF_CTRL_C) exit (0);
  1738.  
  1739.    /* Input detected, unblank if necessary */
  1740.  
  1741.    if (Mask&MASK(bsp_InputSig))
  1742.     {
  1743.      if (BlankerScreen)
  1744.       {
  1745.        if (BlankerClientPort) RemTool (BlankerClientPort);
  1746.        RemTool (BlankerScreen);
  1747.        BlankerScreen=NULL;
  1748.        InitTimeLeft=TimeOut*10L;
  1749.        ON_SPRITE
  1750.       }
  1751.      TimeLeft=InitTimeLeft;
  1752.     }
  1753.  
  1754.    /* client has confirmed that it is still alive */
  1755.  
  1756.    if (Mask&MASK(bsp_ClientSig)) TimeLeft=InitTimeLeft;
  1757.  
  1758.    /* time run out */
  1759.  
  1760.    if (TimeLeft==0L)
  1761.     if (BlankerScreen)
  1762.      {
  1763.       TimeLeft=10L; /* check again after on second to keep screen in front */
  1764.       SetRGB4 (&BlankerScreen->ViewPort,0,0,0,0);
  1765.       SetRGB4 (&BlankerScreen->ViewPort,1,0,0,0);
  1766.  
  1767.       if (IntuitionBase->FirstScreen!=BlankerScreen)
  1768.        {
  1769.         ScreenToFront (BlankerScreen);
  1770.         SpritesOff();
  1771.        }
  1772.       /* Client Time Out reached, turn entire screen black */
  1773.      }
  1774.     else
  1775.      {
  1776.       AddTool (BlankerScreen=CreateScreen(ModeList,DisplayMode),
  1777.                CloseScreen,0L);
  1778.       BlankerClientMsg.bcm_Message.mn_Node.ln_Type=NT_MESSAGE;
  1779.       BlankerClientMsg.bcm_Message.mn_Node.ln_Pri=0;
  1780.       BlankerClientMsg.bcm_Message.mn_Length=sizeof(struct BlankerClientMsg);
  1781.       BlankerClientMsg.bcm_Message.mn_ReplyPort=FINDPROCPORT;
  1782.  
  1783.       BlankerClientMsg.bcm_Screen=BlankerScreen;
  1784.       BlankerClientMsg.bcm_SigMask=1L<<bsp_ClientSig;
  1785.       BlankerClientMsg.bcm_Change=Change;
  1786.       BlankerClientMsg.bcm_Trail=Trail;
  1787.       BlankerClientMsg.bcm_Cycle=Cycle;
  1788.       /* try to start Client */
  1789.       if (BlankerClientPort=CreateBlankerClient(RotorClientProcess,
  1790.                                                 &BlankerClientMsg))
  1791.        {
  1792.         TimeLeft=InitTimeLeft=10L*ClientTimeOut;
  1793.         AddTool (BlankerClientPort,DeleteBlankerClient,
  1794.                  (LONG)&BlankerClientMsg);
  1795.        }
  1796.      }
  1797.   }
  1798. }
  1799.